﻿

#ifndef HPL_FILE_H
#define HPL_FILE_H

#include "node.h"

#include <string>

#include <fstream>

namespace hpl
{

/** Source file.*/
class File: public Node
{
public:
	/** Constructor. Opens and parses file.
	\param path Full path to the file - inclusive it's name.*/
	File(const std::string& path, Program* program);
	
	/** Openes and checks file's encoding.
	\return true if file was successfully opened.*/
	bool Open(const std::string& path);
	
	/** Do the whole parsing job.*/
	void Parse();
	
	const std::string& GetPath() const;
	const std::string& GetName() const;
	
	bool IsOpened() const;
	bool HasBom() const;
	unsigned char GetEncoding() const;
	
	void Step(const char token);
	
private:
	
	void Handle_UNDEFINED(const char token);
	
	/** Full path to the file - inclusive it's name.*/
	std::string path;
	/** Name of the file from it's full path - inclusive it's extension.*/
	std::string name;
	
	/** Token-by-token parsing stream.*/
	ifstream inputStream;
	
	bool isOpened;
	
	/** true - file has "Byte order mark" in case of UTF8 encoding.*/
	bool hasBom;
	
	/** All possible encodings.*/
	enum
	{
		UNDEFINED,	/**< File was not even opened.*/
		ANSI,
		UTF8,
	};
	unsigned char encoding;
	
	/** All possible parsing states.*/
	enum
	{
		PS_UNDEFINED,	/**< Was not started yet or consise parsing initial state.*/
		PS_SPACE,	/**< Space symbol occured.*/
		PS_NEW_LINE,
		PS_WORD,
		PS_MACRO,	/**< Collecting hash postfix.*/
	};
	/** Current parsing state.*/
	unsigned char currentState;
	
	/** Need for parsing.*/
	std::string currentWord;
	int currentSpaces;
	int currentNewLines;
	
	int currentLineNumber;
};

}//namespace hpl

#endif//#ifndef HPL_FILE_H

